/*
 * Balancin.cpp
 *
 *  Created on: 09/10/2013
 *      Author: juliansci
 */

#include "Balancin.h"
#include <iostream>
#include "UnidadLogica.h"


Balancin::Balancin(double x, double y, double ancho, double alto,
		string pathImagen) :
		Elemento(x, y, ancho, alto, pathImagen) {
	this->posSogaIzqX = 0;
	this->posSogaIzqY = 0;
	this->sogaIzqUnida = NULL;
	this->posSogaDerX = ancho;
	this->posSogaDerY = 0;
	this->sogaDerUnida = NULL;
	this->sogaIzqInicial = false;
	this->sogaDerInicial = false;
}

Balancin::~Balancin() {
	// TODO Auto-generated destructor stub
}

void Balancin::rotar(double angulo) {
	if (angulo <= 45 || (angulo >= 315 && angulo <= 360)) {
		this->setAnguloRotacion(angulo);
		this->actualizarReferencias();
	}
}

bool Balancin::aceptaSoga() {
	if (this->sogaIzqUnida && this->sogaDerUnida)
		return false;
	return true;
}

void Balancin::activarSogaPosInicial() {
	this->sogaIzqInicial = true;
}
void Balancin::activarSogaPosFinal() {
	this->sogaDerInicial = true;
}

void Balancin::mover(double centroX, double centroY) {
	Elemento::mover(centroX, centroY);
	this->actualizarReferencias();
}

void Balancin::agregarSogaInicial(Elemento* soga) {
	

	if (this->sogaIzqUnida) {
		cout << "Habia simulado anteriormente " << endl;
		if (this->sogaIzqUnida->getIdElemento() == soga->getIdElemento()) {
			pair<double,double> parXYAObtener = this->obtenerPosicionSoga(0);
			//soga->setPosicionInicial(this->getX(), this->getY());
			soga->setPosicionInicial(parXYAObtener.first,parXYAObtener.second);
			return;
		}
	}

	if (this->sogaDerUnida) {
		cout << "Habia simulado anteriormente " << endl;
		if (this->sogaDerUnida->getIdElemento() == soga->getIdElemento()) {
			pair<double,double> parXYAObtener = this->obtenerPosicionSoga(1);
//			soga->setPosicionInicial(this->getX() + this->posSogaDerX,
//					this->getY() + this->posSogaDerY);
			soga->setPosicionInicial(parXYAObtener.first,parXYAObtener.second);
			return;
		}
	}
	
	pair<double, double> posicionInicioSoga = soga->getPosicionInicial();
	double medioBalancin = this->getX() + this->getAncho() / 2;
	if (posicionInicioSoga.first <= medioBalancin) {
		pair<double,double> parXYAObtener = this->obtenerPosicionSoga(0);
//		soga->setPosicionInicial(this->getX() + this->posSogaIzqX,
//				this->getY() + this->posSogaIzqY);
		soga->setPosicionInicial(parXYAObtener.first,parXYAObtener.second);
		this->sogaIzqUnida = soga;
		this->sogaIzqInicial = true;
	} else {
		pair<double,double> parXYAObtener = this->obtenerPosicionSoga(1);
//		soga->setPosicionInicial(this->getX() + this->posSogaDerX,
//				this->getY() + this->posSogaDerY);
		soga->setPosicionInicial(parXYAObtener.first,parXYAObtener.second);
		this->sogaDerUnida = soga;
		this->sogaDerInicial = true;
	}

}

void Balancin::agregarSogaFinal(Elemento* soga) {
	
	if (this->sogaIzqUnida) {
		if (this->sogaIzqUnida->getIdElemento() == soga->getIdElemento()) {
			pair<double,double> parXYAObtener = this->obtenerPosicionSoga(0);
			soga->setPosicionFinal(parXYAObtener.first,parXYAObtener.second);
			//soga->setPosicionFinal(this->getX(), this->getY());
			this->sogaIzqUnida = soga;
			this->sogaIzqInicial = false;
			return;
		}
	}

	if (this->sogaDerUnida) {
		if (this->sogaDerUnida->getIdElemento() == soga->getIdElemento()) {
			pair<double,double> parXYAObtener = this->obtenerPosicionSoga(1);
			soga->setPosicionFinal(parXYAObtener.first,parXYAObtener.second);
//			soga->setPosicionFinal(this->getX() + this->posSogaDerX,
//					this->getY() + this->posSogaDerY);
			this->sogaDerUnida = soga;
			this->sogaDerInicial = false;
			return;
		}
	}

	pair<double, double> posicionFinSoga = soga->getPosicionFinal();
	double medioBalancin = this->getX() + this->getAncho() / 2;

	if (posicionFinSoga.first <= medioBalancin) {
		pair<double,double> parXYAObtener = this->obtenerPosicionSoga(0);
		soga->setPosicionFinal(parXYAObtener.first,parXYAObtener.second);
//		soga->setPosicionFinal(this->getX() + this->posSogaIzqX,
//				this->getY() + this->posSogaIzqY);
		this->sogaIzqUnida = soga;
		this->sogaIzqInicial = false;
	} else {
		pair<double,double> parXYAObtener = this->obtenerPosicionSoga(1);
		soga->setPosicionFinal(parXYAObtener.first,parXYAObtener.second);
//		soga->setPosicionFinal(this->getX() + this->posSogaDerX,
//				this->getY() + this->posSogaDerY);
		this->sogaDerUnida = soga;
		this->sogaDerInicial = false;
	}

}

void Balancin::eliminarSoga(Elemento* soga) {
//	cout << "soga a eliminar con id: " << soga->getIdElemento() << endl;
	if (this->sogaIzqUnida) {
		if (this->sogaIzqUnida->getIdElemento() == soga->getIdElemento()){
			cout << "Elimino soga izquierda" << endl;
			this->sogaIzqUnida = NULL;
			this->sogaIzqInicial = false;
			cout << "Elimine soga izquierda unida" << endl;
			return;
		}
	}

	if (this->sogaDerUnida) {
		cout << "soga der con id: " << this->sogaDerUnida->getIdElemento()
				<< endl;

		if (this->sogaDerUnida->getIdElemento() == soga->getIdElemento()){
			cout << "Elimino soga derecha" << endl;
			this->sogaDerUnida = NULL;
			this->sogaDerInicial = false;
			return;
		}
	}

}

int Balancin::seSuperpone(Elemento* elemento) {
	if (elemento->getTipo() == "soga")
		return 0;
	return 2;
}

void Balancin::eliminarReferencias(list<Elemento*>* elementosCanvas) {
	pair<Elemento*, Elemento*> extremosSoga;
	pair<Elemento*, Elemento*> extremosSogaIzq, extremosSogaDer;

	if (this->sogaIzqUnida) {

		this->sogaIzqUnida->eliminarReferencias(elementosCanvas);
//		extremosSogaIzq = this->sogaIzqUnida->obtenerExtremosSoga();
//		elementosCanvas->remove(this->sogaIzqUnida);
//		extremosSogaIzq.first->eliminarSoga(this->sogaIzqUnida);
//		extremosSogaIzq.second->eliminarSoga(this->sogaIzqUnida);
		delete this->sogaIzqUnida;
		this->sogaIzqUnida = NULL;
//		this->sogaIzqInicial = false;

	}
	if (this->sogaDerUnida) {
		this->sogaDerUnida->eliminarReferencias(elementosCanvas);
//		extremosSogaDer = this->sogaDerUnida->obtenerExtremosSoga();
//		extremosSogaDer.first->eliminarSoga(this->sogaDerUnida);
//		extremosSogaDer.second->eliminarSoga(this->sogaDerUnida);
//		elementosCanvas->remove(this->sogaDerUnida);
		delete this->sogaDerUnida;
		this->sogaDerUnida=NULL;
//		this->sogaDerInicial = false;
	}
}

void Balancin::actualizarReferencias() {

	if (this->sogaIzqUnida != NULL) {

		pair<double,double> parXYAObtener = this->obtenerPosicionSoga(0);

		if (this->sogaIzqInicial) {

			this->sogaIzqUnida->setPosicionInicial(
					parXYAObtener.first,
					parXYAObtener.second);
		} else {
			this->sogaIzqUnida->setPosicionFinal(
					parXYAObtener.first,
					parXYAObtener.second);
		}
	}
	if (this->sogaDerUnida != NULL) {

		pair<double,double> parXYAObtener = this->obtenerPosicionSoga(1);

		if (this->sogaDerInicial) {
			this->sogaDerUnida->setPosicionInicial(
					parXYAObtener.first,
					parXYAObtener.second);
		} else {
			this->sogaDerUnida->setPosicionFinal(
					parXYAObtener.first,
					parXYAObtener.second);
		}
	}

}

int Balancin::haySogaIzqUnida() {
	if (this->sogaIzqUnida)
		return 1;
	return 0;
}
int Balancin::haySogaDerUnida() {
	if (this->sogaDerUnida)
		return 1;
	return 0;
}

bool Balancin::esBasico() {
	return false;
}

bool Balancin::sogaEnPosInicial() {
	return this->sogaIzqInicial;
}

bool Balancin::sogaEnPosFinal() {
	return this->sogaDerInicial;

}

pair<Elemento*, Elemento*> Balancin::obtenerExtremos() {
	pair<Elemento*, Elemento*> extremos;
	extremos.first = NULL;
	extremos.second = NULL;
	if (this->sogaIzqUnida) {
		extremos.first = this->sogaIzqUnida;
	}
	if (this->sogaDerUnida) {
		extremos.second = this->sogaDerUnida;
	}
	return extremos;
}

void Balancin::setSogaInicial(Elemento* elem) {
	this->sogaIzqUnida = elem;
}

void Balancin::setSogaFinal(Elemento* elem) {
	this->sogaDerUnida = elem;

}


void Balancin::jointearElemento(b2World* world){
	BalancinFisica* balancinFisica = (BalancinFisica*)this->getEntidadFisica();
	balancinFisica->tieneSogaDerecha(this->sogaDerInicial);
	balancinFisica->tieneSogaIzquierda(this->sogaIzqInicial);

}

pair<double,double> Balancin::obtenerPosicionSoga(int sentido){

	pair<double,double> posicionXYAObtener;

	// Soga izquierda
	if (sentido == 0){
		double angulo = this->getAnguloRotacion() - 360;

		double xTrasladado = - this->getAncho()/2;
		double yTrasladado = 0;

		double xRotado = xTrasladado * cos(angulo * PI / 180.0) +
				yTrasladado	* sin(angulo * PI/ 180.0);
		double yRotado = -xTrasladado * sin(angulo * PI / 180.0)	+
				yTrasladado	* cos(angulo * PI/ 180.0);

		double xAObtener = xRotado + this->getAncho() / 2 + this->getX();
		double yAObtener = -yRotado + this->getY();
		posicionXYAObtener.first = xAObtener;
		posicionXYAObtener.second = yAObtener;
	}
	// Soga derecha
	else if (sentido == 1){
		double angulo = 360 - this->getAnguloRotacion();

		double xTrasladado = this->getAncho()/2;
		double yTrasladado = 0;

		double xRotado = xTrasladado * cos(angulo * PI / 180.0) -
				yTrasladado	* sin(angulo * PI/ 180.0);
		double yRotado = xTrasladado * sin(angulo * PI / 180.0)	+
				yTrasladado	* cos(angulo * PI/ 180.0);

		double xAObtener = xRotado + this->getAncho() / 2 + this->getX();
		double yAObtener = -yRotado + this->getY();
		posicionXYAObtener.first = xAObtener;
		posicionXYAObtener.second = yAObtener;
	}

	return posicionXYAObtener;
}
